#!/bin/env python2
# -*- coding: utf-8 -*-
from __future__ import division
import argparse, readline, glob, sys
from utils import AttrDict, summary
from argparse import ArgumentError
from alignment import AlignmentModel
from munteanu import MunteanuModel

def interactive_mode(params):
    state = AttrDict(alignment_model=None, munteanu_model=None)

    #TODO: better usage message
    parser = argparse.ArgumentParser(
            description='Extraction of parallel sentences from a bilingual corpus',
            add_help=False)
    subparsers = parser.add_subparsers()
    
    parser_help = subparsers.add_parser('help', help='print the help message')
    parser_exit = subparsers.add_parser('exit', help='exit the prompt')
    parser_init = subparsers.add_parser('init', help='initialize the alignment model', argument_default=argparse.SUPPRESS)
    parser_train = subparsers.add_parser('train', help='train the classifier', argument_default=argparse.SUPPRESS)
    parser_test = subparsers.add_parser('test', help='evaluate the classifier', argument_default=argparse.SUPPRESS)

    parser_init.add_argument('giza_model', help='giza model')
    parser_train.add_argument('train_corpus', help='training corpus')
    parser_test.add_argument('test_corpus', help='test corpus')
    
    parser_init.add_argument('-c', '--giza', help='type of model used', dest='giza_model_type')

    parser_train.add_argument('-b', '--no-filter', dest='filtering', help='enable candidate filtering', action='store_false')
    parser_train.add_argument('-m', '--min-overlap', dest='min_overlap', help='minimum word-overlap')
    parser_train.add_argument('-r', '--length-ratio', dest='length_ratio', help='maximum length ratio')
    parser_train.add_argument('-n', '--train', type=int, help='training size', dest='n_positive')
    parser_train.add_argument('-a', '--train-neg', type=int, help='training size (negative)', dest='n_negative')

    parser_test.add_argument('-l', '--test', type=int, help='test size', dest='n_test')
    parser_test.add_argument('-f', '--noise-level', type=int, help='noise level', dest='noise_level')
    parser_test.add_argument('-t', '--threshold', type=float, help='classifier threshold')
    parser_test.add_argument('-g', '--reference', help='location of the alignment reference, if the input is not a bitext',
            default=None)
    parser_test.add_argument('-k', '--evaluation-method',
            help='evaluation method (default, one_one, sentence_level)', dest='evaluation_method')
    
    alignment_model = None
    munteanu_model = None
   
    def init(args):
        state.alignment_model = AlignmentModel(args.giza_model, args)
    def train(args):
        if state.alignment_model is None:
            print 'error: the alignment model has not been initialized, use `init\''
            return
        state.munteanu_model = MunteanuModel(state.alignment_model, args.train_corpus, args)
    def test(args):
        if state.munteanu_model is None:
            print 'error: no munteanu model has been trained, use `train\''
            return
        if args.reference is not None:
            statistics = state.munteanu_model.evaluation_with_reference(args.input_corpus, args.reference, args)
        else:
            statistics = state.munteanu_model.evaluation(args.test_corpus, args)
        summary(statistics)
    def help(args):
        parser.print_help()
    
    parser_help.set_defaults(func=help)
    parser_init.set_defaults(func=init)
    parser_train.set_defaults(func=train)
    parser_test.set_defaults(func=test)
    parser_exit.set_defaults(func=lambda _: sys.exit(42))
    
    commands = ['help', 'init', 'train', 'test', 'exit']
    try:
        readline.read_history_file()
    except IOError:
        pass
    def complete(text, state):
        return (sorted([cmd for cmd in commands if cmd.startswith(text)]) +
                glob.glob(text + '*') + [None])[state]
    readline.set_completer_delims(' \t')
    readline.parse_and_bind("tab: complete")
    readline.set_completer(complete)

    while True:
        try:
            cmd = raw_input('> ')
            if cmd:
                args = parser.parse_args(cmd.split())
                args.func(AttrDict(args.__dict__).setdefault(**params))
        except SystemExit as e:
            # We don't want argparse's exit codes (0, 1, 2) to close the program.
            if e.message == 42:
                return
        except EOFError:
            readline.write_history_file()
            print('')
            return

if __name__ == '__main__':
    try:
        src_lang, trg_lang = sys.argv[1:]
    except:
        sys.exit('usage: {} SRC_LANG TRG_LANG'.format(sys.argv[0]))

    interactive_mode(AttrDict(src_lang=src_lang, trg_lang=trg_lang))

